//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<object_ref.h>
///	@path	~/src/object/
///	@date	2007/06/27
///	@desc	Object reference.

#pragma once

#include "xeres.h"

#include "object/object_ref_base.h"

namespace xeres {

	/*!
		\class	Ref
		\brief	IObject reference, holds an Object (pointer).
		\details
			Ref provide a pointer-like way to access IObject instance. It uses auto reference count to
			manage object ownership, and release it while destruction. And Ref manages type cast operation.
			Instead of calling ObjectFactory::IsCompatible Ref could cast compatible types between different references safely. <BR>
			<BR>
		\topic{ Using Ref: }
			There's 3 types of reference: Ref, RefWeak, RefPass.<BR>
			Ref is used for stable object holding, for class member or global variable.
			Because it increase & decrease reference count at assignment, if Ref is used for argument or return value,
			will cause huge interlocked operation and <b>great impact of program performance.</b><BR>
			<BR>
		\topic{ Type casting: }
			Ref, RefWeak & RefPass can perform type casting automatically.
			Any compatible references can assign to different type of reference.<BR>
		\code
			// Create a CVar.
			Ref<IVar> var = new CVar;
			// ... do sth.
			// We want to manipulate CVar attributes.
			Ref<CVar> cvar = var;
			// ...and so on.
		\endcode

		\remarks
			Program will cause a fatal error while trying to cast incompatible types.

		\sa	RefWeak, RefPass
	*/
	template<
		typename _IObjectClass // IObject interface or class
	> class Ref : public RefBase< _IObjectClass , Ref< _IObjectClass > >
	{
	public:

		/// \name Constructor & Destructor
		//@{

		/// \ctor
		Ref( void )
			: m_object( NULL )
		{
		}

		/*!
			\ctor_set
			\details
				Reference the same type of IObject instance <b>without type casting</b>, and increase/keep reference of object.
			\param[in]		object		Source object instance, can be NULL.
			\param[in]		inc_ref		True to increase object reference, false to keep current reference.
		*/
		explicit Ref( _IObjectClass * object , bool inc_ref = true )
			: m_object( object )
		{
			if( m_object && inc_ref )
				m_object->AddRef();
		}

		/*!
			\ctor_copy
			\details
				Copy IObject instance from another type of RefPass <b>with type casting</b>.<BR>
				As RefPass always transfers ownership, IObject instance will <b>NOT increase</b> reference count while assignment.
				The ownership of RefPass 's reference will be transfer to new Ref.<BR>
			\param[in,out]		rhs		Source object instance holder.
		*/
		template< typename _OtherIObject > Ref( const RefPass<_OtherIObject>& rhs )
			: m_object( NULL )
		{
			rhs.GetObject( m_object );
		}

		/*!
			\ctor_copy
			\details
				Copy IObject instance from another type of RefWeak <b>with type casting</b>.<BR>
				RefWeak doesn't have any ownership of reference, so new Ref <b>increases</b> reference count while assignment.
				RefWeak still holds borrowed ownership of IObject.
			\param[in]			rhs		Source object instance holder.
		*/
		template< typename _OtherIObject > Ref( const RefWeak<_OtherIObject>& rhs )
			: m_object( NULL )
		{
			rhs.GetObject( m_object );
		}

		/*!
			\ctor_copy
			\details
				Duplicate ownership of another Ref <b>without type casting</b>.<BR>
				Reference count <b>increases</b> while assignment.
			\param[in]		rhs		Source object instance holder.
		*/
		Ref( const Ref& rhs )
			: m_object( rhs.m_object )
		{
			if( m_object )
				m_object->AddRef();
		}

		/*!
			\ctor_copy
			\details
				Duplicate ownership of another Ref <b>with type casting</b>.<BR>
				If source Ref has valid IObject instance, its reference count will be <b>increase</b> while assignment.
			\param[in]		rhs		Source object instance holder.
		*/
		template< typename _OtherIObject > explicit Ref( const Ref< _OtherIObject >& rhs )
			: m_object( NULL )
		{
			rhs.GetObject( m_object );
		}

		/*!
			\ctor_set
			\details
				Reference another IObject instance <b>with type casting</b>, and increase/keep reference of object.
			\param[in]		object		Source object instance, can be NULL.
			\param[in]		inc_ref		True to increase object reference, false to keep current reference.
		*/
		template< typename _OtherIObject > Ref( _OtherIObject * object , bool inc_ref = true )
			: m_object( NULL )
		{
			if( inc_ref )
				DuplicateOwnership< _OtherIObject , _IObjectClass >( object , m_object );
			else
				BorrowOwnership< _OtherIObject , _IObjectClass >( object , m_object );
		}

		/// \dtor
		~Ref( void )
		{
			if( m_object )
				m_object->ReleaseRef();
		}

		//@}

		/// \name Ownership Management
		//@{

		/*! 
			\brief	Set IObject Instance to Ref.
			\details
				Set new instance to ref.<BR>
		*/
		template< typename _OtherIObject > void SetObject( _OtherIObject * ptr ) const
		{

		}

		/*!
			\brief	Get IObject instance pointer of Ref.
			\details
				For direct manipulation using pointer of IObject.<BR>
				Function perform explicit type casting by specifying template type.
			\remarks
				<b>Notice the pointer pass to function MUST be NULL, make sure it's cleared.</b>
			\param[in,out]		ptr		Pointer reference to receive IObject pointer, MUST be NULL.

			\sa	RefPass::GetObject, RefWeak::GetObject
		*/
		template< typename _OtherIObject > void GetObject( _OtherIObject *& ptr ) const
		{
			assert( ptr == NULL );
			DuplicateOwnership< _IObjectClass , _OtherIObject >( m_object , ptr );
		}

		/// Specialization of GetObject, <b>without type casting</b>, for reducing redundant runtime type casting.
		template<> void GetObject< IObject >( IObject *& ptr ) const
		{
			assert( ptr == NULL );
			ptr = m_object;
			if( ptr )
				ptr->AddRef();
		}

		/// Specialization of GetObject, <b>without type casting</b>, for reducing redundant runtime type casting.
		void GetObject( _IObjectClass *& ptr ) const
		{
			assert( ptr == NULL );
			ptr = m_object;
			if( ptr )
				ptr->AddRef();
		}

		/*!
			\brief	Borrow reference from IObject instance.
			\details
				Borrow reference will omit reference count increment.<BR>
				When using reference for temporary variable or as argument, BorrowObject can reduce reference increment.
			\remarks
				<b>Notice the pointer pass to function MUST be NULL, make sure it's cleared.</b>
			\param[in,out]		ptr		Pointer reference to receive IObject pointer, MUST be NULL.

			\sa	RefPass::BorrowObject, RefWeak::BorrowObject
		*/
		template< typename _OtherIObject > void BorrowObject( _OtherIObject *& ptr ) const
		{
			assert( ptr == NULL );
			BorrowOwnership< _IObjectClass , _OtherIObject >( m_object , ptr );
		}

		/// Specialization of BorrowObject, <b>without type casting</b>, for reducing redundant runtime type casting.
		template<> void BorrowObject< IObject >( IObject *& ptr ) const
		{
			assert( ptr == NULL );
			ptr = m_object;
		}

		/// Specialization of BorrowObject, <b>without type casting</b>, for reducing redundant runtime type casting.
		void BorrowObject( _IObjectClass *& ptr ) const
		{
			assert( ptr == NULL );
			ptr = m_object;
		}

		//@}

		// Special assignment for passing NULL in.
		Ref& operator = ( int rhs )
		{
			assert( rhs == NULL );
			if( m_object )
				m_object->ReleaseRef();
			m_object = NULL;
			return *this;
		}

		// Assignment.
		Ref& operator = ( const Ref& rhs )
		{
			if( m_object )
				m_object->ReleaseRef();
			m_object = rhs.m_object;
			if( m_object )
				m_object->AddRef();
			return *this;
		}

		Ref& operator = ( _IObjectClass * rhs )
		{
			if( m_object )
				m_object->ReleaseRef();
			m_object = rhs;
			if( m_object )
				m_object->AddRef();
			return *this;
		}

		template< typename _OtherIObject > Ref& operator = ( _OtherIObject * rhs )
		{
			if( m_object )
			{
				m_object->ReleaseRef();
				m_object = NULL;
			}
			if( rhs )
			{
				DuplicateOwnership< _OtherIObject , _IObjectClass >( rhs , m_object );
			}
			return *this;
		}

		// Assignment with type casting.
		template< typename _OtherIObject > Ref& operator = ( const Ref<_OtherIObject>& rhs )
		{
			if( m_object )
			{
				m_object->ReleaseRef();
				m_object = NULL;
			}
			
			rhs.GetObject( m_object );
			return *this;
		}

		// From return value?
		Ref& operator = ( const RefPass< _IObjectClass >& rhs )
		{
			if( m_object )
				m_object->ReleaseRef();
			m_object = NULL;
			rhs.GetObject( m_object );
			return *this;
		}

		template< typename _OtherIObject > Ref& operator = ( const RefPass< _OtherIObject >& rhs )
		{
			if( m_object )
				m_object->ReleaseRef();
			m_object = NULL;
			rhs.GetObject( m_object );
			return *this;
		}

		// Assign from weak reference.
		Ref& operator = ( const RefWeak< _IObjectClass >& rhs )
		{
			if( m_object )
				m_object->ReleaseRef();
			m_object = NULL;
			rhs.GetObject( m_object );
			return *this;
		}

		template< typename _OtherIObject > Ref& operator = ( const RefWeak< _OtherIObject >& rhs )
		{
			if( m_object )
				m_object->ReleaseRef();
			m_object = NULL;
			rhs.GetObject( m_object );
			return *this;
		}

	private:

		friend class RefBase< _IObjectClass , Ref< _IObjectClass > >;

		// data
		mutable _IObjectClass *		m_object;
	};

	/*!
		\class	RefPass
		\brief	IObject reference as passing value, transfers ownership.
		\details
			Likes Ref, RefPass holds reference of IObject instance, but don't hold them for storing,
			RefPass <b>transfers</b> them. While trying to get internal pointer or assigning a RefPass to Ref,
			ownership will be transfered to destination, internal pointer will be cleared.<BR>
			So RefPass just does the same thing as Ref does, but just <b>doesn't decrease reference count</b> while assignment.
			But if RefPass found it still has ownership of IObject instance while destructing, it release reference.<BR>
			RefPass just holds an reference, transfer it to another or release it if not transfered.
			<BR>
		\topic{ Using RefPass: }
			There's 3 types of reference: Ref, RefWeak, RefPass.<BR>
			RefPass is designed for return value passing, to reduce redundant reference increment/decrement.<BR>
		\topic{ Type casting: }
			Ref, RefWeak & RefPass can perform type casting automatically.
			Any compatible references can assign to different type of reference.<BR>
		\code
			// Create a CVar.
			RefPass<IVar> var = new CVar;
			// ... do sth.
			// We need to return it as CVar.
			return RefPass<CVar>( var );
		\endcode
			In this case, new CVar instance just increase reference count once(while assigning new pointer to RefPass).<BR>
			Any RefPass assignment just transfers ownership.<BR>

		\remarks
			Program will cause a fatal error while trying to cast incompatible types.

		\sa	Ref, RefWeak
	*/
	template<
		typename _IObjectClass // IObject interface or class
	> class RefPass : public RefBase< _IObjectClass , RefPass< _IObjectClass > >
	{
	public:

		/// \name Constructor & Destructor
		//@{

		/*!
			\ctor_set
			\details
				Special constructor for NULL pointer passing in.
			\param[in]		null_pointer		Dummy parameter, must be NULL.
		*/
		RefPass( void * null_pointer )
			: m_object( NULL )
		{
			assert( null_pointer == NULL );
		}

		/*!
			\ctor_set
			\details
				Special constructor for NULL pointer passing in.
			\param[in]		null_pointer		Dummy parameter, must be NULL.
		*/
		explicit RefPass( int null_pointer )
			: m_object( NULL )
		{
			assert( null_pointer == 0 );
		}

		/*!
			\ctor_set
			\details
				Reference the same type of IObject instance <b>without type casting</b>, and increase/keep reference of object.
			\param[in]		object		Source object instance, can be NULL.
			\param[in]		inc_ref		True to increase object reference, false to keep current reference.
		*/
		explicit RefPass( _IObjectClass * object , bool inc_ref = true )
			: m_object( object )
		{
			if( m_object && inc_ref )
				m_object->AddRef();
		}

		/*!
			\ctor_copy
			\details
				Copy IObject instance from another type of Ref <b>with type casting</b>.<BR>
				RefPass duplicates source Ref 's ownership, instance will <b>increase</b> reference count.
			\param[in,out]		rhs		Source object instance holder.
		*/
		template< typename _OtherIObject > RefPass( const Ref<_OtherIObject>& rhs )
			: m_object( NULL )
		{
			rhs.GetObject( m_object );
		}

		/*!
			\ctor_copy
			\details
				Transfers ownership <b>with type casting</b> between 2 RefPass, source RefPass will <b>clear</b> its reference.<BR>
				Notice instance's reference count will <b>NOT</b> change while assignment.<BR>
				This operation is designed for return value passing. Assuming that we have to return an IObject instance through
				several functions, Ref will increase & decrease reference count several times. RefPass is efficient in such case.<BR>
			\param[in,out]		rhs		Source object instance holder.
		*/
		template< typename _OtherIObject > RefPass( const RefPass<_OtherIObject>& rhs )
			: m_object( NULL )
		{
			rhs.GetObject( m_object );
		}

		/*!
			\ctor_copy
			\details
				Copy IObject instance from another type of RefWeak <b>with type casting</b>.<BR>
				RefWeak doesn't have any ownership of reference, so new Ref <b>increases</b> reference count while assignment.
				RefWeak still holds borrowed ownership of IObject.
			\param[in]			rhs		Source object instance holder.
		*/
		template< typename _OtherIObject > RefPass( const RefWeak<_OtherIObject>& rhs )
			: m_object( NULL )
		{
			rhs.GetObject( m_object );
		}

		/*!
			\ctor_copy
			\details
				Transfer ownership of another RefPass <b>without type casting</b>. <BR>
				Reference count <b>increases</b> while assignment.
			\param[in]		rhs		Source object instance holder.
		*/
		RefPass( const RefPass& rhs )
			: m_object( rhs.m_object )
		{
			// transfers ownership
			rhs.m_object = NULL;
		}

		/*!
			\ctor_set
			\details
				Reference another IObject instance <b>with type casting</b>, and increase/keep reference of object.
			\param[in]		object		Source object instance, can be NULL.
			\param[in]		inc_ref		True to increase object reference, false to keep current reference.
		*/
		template< typename _OtherIObject > RefPass( _OtherIObject * object , bool inc_ref = true )
			: m_object( NULL )
		{
			if( inc_ref )
				DuplicateOwnership< _OtherIObject , _IObjectClass >( object , m_object );
			else
				BorrowOwnership< _OtherIObject , _IObjectClass >( object , m_object );
		}

		/// \dtor
		~RefPass( void )
		{
			if( m_object )
				m_object->ReleaseRef();
		}

		//@}

		/// \name Ownership Management
		//@{

		/*!
			\brief	Get IObject instance pointer of Ref.
			\details
				For direct manipulation using pointer of IObject.<BR>
				Function perform explicit type casting by specifying template type.<BR>
				RefPass <b>will transfer</b> its ownership while assignment, clear reference.
			\remarks
				<b>Notice the pointer pass to function MUST be NULL, make sure it's cleared.</b>
			\param[in,out]		ptr		Pointer reference to receive IObject pointer, MUST be NULL.

			\sa	Ref::GetObject, RefWeak::GetObject
		*/
		template< typename _OtherIObject > void GetObject( _OtherIObject *& ptr ) const
		{
			assert( ptr == NULL );
			TransferOwnership< _IObjectClass , _OtherIObject >( m_object , ptr );
		}

		/// Specialization of GetObject, <b>without type casting</b>, for reducing redundant runtime type casting.
		template<> void GetObject< IObject >( IObject *& ptr ) const
		{
			assert( ptr == NULL );
			ptr = m_object;
			// transfered ownership
			m_object = NULL;
		}

		/// Specialization of GetObject, <b>without type casting</b>, for reducing redundant runtime type casting.
		void GetObject( _IObjectClass *& ptr ) const
		{
			assert( ptr == NULL );
			ptr = m_object;
			// transfered ownership
			m_object = NULL;
		}

		/*!
			\brief	Borrow reference from IObject instance.
			\details
				Borrow reference will omit reference count increment.<BR>
				When using reference for temporary variable or as argument, BorrowObject can reduce reference increment.<BR>
			\remarks
				Borrowing reference from RefPass is strongly not recommended. But for efficiency, some situation needs such function.
			\remarks
				<b>Notice the pointer pass to function MUST be NULL, make sure it's cleared.</b>
			\param[in,out]		ptr		Pointer reference to receive IObject pointer, MUST be NULL.

			\sa	Ref::BorrowObject, RefWeak::BorrowObject
		*/
		template< typename _OtherIObject > void BorrowObject( _OtherIObject *& ptr ) const
		{
			assert( ptr == NULL );
			BorrowOwnership< _IObjectClass , _OtherIObject >( m_object , ptr );
		}

		/// Specialization of BorrowObject, <b>without type casting</b>, for reducing redundant runtime type casting.
		template<> void BorrowObject< IObject >( IObject *& ptr ) const
		{
			assert( ptr == NULL );
			ptr = m_object;
		}

		/// Specialization of BorrowObject, <b>without type casting</b>, for reducing redundant runtime type casting.
		void BorrowObject( _IObjectClass *& ptr ) const
		{
			assert( ptr == NULL );
			ptr = m_object;
		}

		//@}

		// Special assignment for passing NULL in.
		RefPass& operator = ( int rhs )
		{
			assert( rhs == NULL );

			if( m_object )
				m_object->ReleaseRef();

			m_object = NULL;

			return *this;
		}

		// Passing reference.
		RefPass& operator = ( const RefPass& rhs )
		{
			if( m_object )
				m_object->ReleaseRef();

			m_object = NULL;
			rhs.GetObject( m_object );

			return *this;
		}

		template<
			typename _OtherIObject
		> RefPass& operator = ( const RefPass< _OtherIObject >& rhs )
		{
			if( m_object )
				m_object->ReleaseRef();

			m_object = NULL;
			rhs.GetObject( m_object );

			return *this;
		}

	private:

		friend class RefBase< _IObjectClass , RefPass< _IObjectClass > >;

		// data
		mutable _IObjectClass *		m_object;
	};

	/*!
		\class	RefWeak
		\brief	IObject reference as borrowed pointer, does not have any ownership.
		\details
			A wrap of pointer, weak reference of IObject instance.<BR>
			RefWeak does not manipulate reference count, it's used for argument passing or temporary type casting.<BR>
			<BR>
		\topic{ Using RefWeak: }
			There's 3 types of reference: Ref, RefWeak, RefPass.<BR>
			Ref is used for stable object holding, for class member or global variable.
			Because it increase & decrease reference count at assignment, if Ref is used for argument or return value,
			will cause huge interlocked operation and <b>great impact of program performance.</b><BR>
			<BR>
		\topic{ Type casting: }
			Ref, RefWeak & RefPass can perform type casting automatically.
			Any compatible references can assign to different type of reference.<BR>
		\code
			// Create a CVar.
			Ref<IVar> var = new CVar;
			// ... do sth.
			// We want to temporary manipulate CVar attributes.
			RefWeak<CVar> cvar = var;
			// ...and so on.
		\endcode

		\remarks
			Program will cause a fatal error while trying to cast incompatible types.

		\sa	Ref, RefPass
	*/
	template<
		typename _IObjectClass // IObject interface or class
	> class RefWeak : public RefBase< _IObjectClass , RefWeak< _IObjectClass > >
	{
	public:

		/// \name Constructor & Destructor
		//@{

		/*!
			\ctor_set
			\details
				Special constructor for NULL pointer passing in.
			\param[in]		null_pointer		Dummy parameter, must be NULL.
		*/
		RefWeak( void * null_pointer = NULL )
			: m_object( NULL )
		{
			assert( null_pointer == NULL );
		}

		/*!
			\ctor_set
			\details
				Special constructor for NULL pointer passing in.
			\param[in]		null_pointer		Dummy parameter, must be NULL.
		*/
		RefWeak( int null_pointer )
			: m_object( NULL )
		{
			assert( null_pointer == 0 );
		}

		/*!
			\ctor_set
			\details
				Reference the same type of IObject instance <b>without type casting</b>, and keep reference of object.<BR>
				Weak reference does not manipulates reference count, should be careful to use.
			\param[in]		object		Source object instance, can be NULL.
		*/
		explicit RefWeak( _IObjectClass * object )
			: m_object( object )
		{
		}

		/*!
			\ctor_copy
			\details
				Duplicate weak reference of another RefWeak <b>without type casting</b>.<BR>
				Reference count <b>keeps</b> while assignment.
			\param[in]		rhs		Source object instance holder.
		*/
		RefWeak( const RefWeak& rhs )
			: m_object( rhs.m_object )
		{
		}

		/*!
			\ctor_copy
			\details
				Borrow reference from a Ref <b>with type casting</b>.<BR>
				Reference count <b>keeps</b> while assignment.
			\param[in]		rhs		Source object instance holder.
		*/
		template< typename _OtherIObject > RefWeak( const Ref<_OtherIObject>& rhs )
			: m_object( NULL )
		{
			rhs.BorrowObject( m_object );
		}

		/*!
			\ctor_copy
			\details
				Borrow reference from a RefPass <b>with type casting</b>.<BR>
				Reference count <b>keeps</b> while assignment.
			\param[in]		rhs		Source object instance holder.
		*/
		template< typename _OtherIObject > explicit RefWeak( const RefPass<_OtherIObject>& rhs )
			: m_object( NULL )
		{
			rhs.BorrowObject( m_object );
		}

		/*!
			\ctor_set
			\details
				Reference another IObject instance <b>with type casting</b>.
				Reference count <b>keeps</b> while assignment.
			\param[in]		object		Source object instance, can be NULL.
		*/
		template< typename _OtherIObject > RefWeak( _OtherIObject * object )
			: m_object( NULL )
		{
			BorrowOwnership< _OtherIObject , _IObjectClass >( object , m_object );
		}

		/*!
			\ctor_copy
			\details
				Duplicate weak reference of another RefWeak <b>with type casting</b>.<BR>
				Reference count <b>keeps</b> while assignment.
			\param[in]		rhs		Source object instance holder.
		*/
		template< typename _OtherIObject > RefWeak( const RefWeak<_OtherIObject>& rhs )
			: m_object( NULL )
		{
			rhs.BorrowObject( m_object );
		}

		/// \dtor
		~RefWeak( void )
		{
		}

		//@}

		/// \name Ownership Management
		//@{

		/*!
			\brief	Get IObject instance pointer of Ref.
			\details
				For direct manipulation using pointer of IObject.<BR>
				Function perform explicit type casting by specifying template type.<BR>
				RefPass <b>will transfer</b> its ownership while assignment, clear reference.
			\remarks
				<b>Notice the pointer pass to function MUST be NULL, make sure it's cleared.</b>
			\param[in,out]		ptr		Pointer reference to receive IObject pointer, MUST be NULL.

			\sa	Ref::GetObject, RefPass::GetObject
		*/
		template< typename _OtherIObject > void GetObject( _OtherIObject *& ptr ) const
		{
			assert( ptr == NULL );
			DuplicateOwnership< _IObjectClass , _OtherIObject >( m_object , ptr );
		}

		/// Specialization of GetObject, <b>without type casting</b>, for reducing redundant runtime type casting.
		template <> void GetObject< IObject >( IObject *& ptr ) const
		{
			assert( ptr == NULL );
			ptr = m_object;
			if( ptr )
				ptr->AddRef();
		}

		/// Specialization of GetObject, <b>without type casting</b>, for reducing redundant runtime type casting.
		void GetObject( IObject *& ptr ) const
		{
			assert( ptr == NULL );
			ptr = m_object;
			if( ptr )
				ptr->AddRef();
		}

		/*!
			\brief	Borrow reference from IObject instance.
			\details
				Borrow reference will omit reference count increment.<BR>
				When using reference for temporary variable or as argument, BorrowObject can reduce reference increment.<BR>
			\remarks
				Borrowing reference from RefPass is strongly not recommended. But for efficiency, some situation needs such function.
			\remarks
				<b>Notice the pointer pass to function MUST be NULL, make sure it's cleared.</b>
			\param[in,out]		ptr		Pointer reference to receive IObject pointer, MUST be NULL.

			\sa	Ref::BorrowObject, RefPass::BorrowObject
		*/
		template< typename _OtherIObject > void BorrowObject( _OtherIObject *& ptr ) const
		{
			assert( ptr == NULL );
			BorrowOwnership< _IObjectClass , _OtherIObject >( m_object , ptr );
		}

		/// Specialization of BorrowObject, <b>without type casting</b>, for reducing redundant runtime type casting.
		template <> void BorrowObject< IObject >( IObject *& ptr ) const
		{
			assert( ptr == NULL );
			ptr = m_object;
		}

		/// Specialization of BorrowObject, <b>without type casting</b>, for reducing redundant runtime type casting.
		void BorrowObject( _IObjectClass *& ptr ) const
		{
			assert( ptr == NULL );
			ptr = m_object;
		}

		//@}

		// Special assignment for passing NULL in.
		RefWeak& operator = ( int rhs )
		{
			assert( rhs == NULL );
			m_object = NULL;
			return *this;
		}

		// Assignment.
		RefWeak& operator = ( const RefWeak< _IObjectClass >& rhs )
		{
			m_object = NULL;
			rhs.BorrowObject( m_object );
			return *this;
		}

		template< typename _OtherIObject > RefWeak& operator = ( const RefWeak< _OtherIObject >& rhs )
		{
			m_object = NULL;
			rhs.BorrowObject( m_object );
			return *this;
		}

	private:

		friend class RefBase< _IObjectClass , RefWeak< _IObjectClass > >;

		// data
		mutable _IObjectClass *		m_object;
	};

} // namespace xeres
